package com.vshop.platform.system.crud.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.vshop.framework.core.constant.Const;
import com.vshop.framework.core.exception.ServiceException;
import com.vshop.framework.core.util.MapstructUtil;
import com.vshop.framework.core.util.StringConst;
import com.vshop.framework.core.util.TreeBuildUtil;
import com.vshop.platform.system.crud.dao.SysDeptDao;
import com.vshop.platform.system.crud.dao.SysRoleDeptDao;
import com.vshop.platform.system.domain.entity.SysDept;
import com.vshop.platform.system.domain.param.SysDeptParam;
import com.vshop.platform.system.domain.vo.SysDeptVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@Service
public class SysDeptService {

    private final DataScopeService dataScopeService;
    private final SysDeptDao sysDeptDao;
    private final SysRoleDeptDao sysRoleDeptDao;

    public List<SysDeptVo> list(SysDeptParam param) {
        QueryWrapper queryWrapper = sysDeptDao.buildQueryWrapper(param);
        return sysDeptDao.listAs(queryWrapper, SysDeptVo.class);
    }

    public boolean save(SysDeptParam param) {

        if (sysDeptDao.checkExistDeptName(param)) {
            throw new ServiceException("新增部门'" + param.getDeptName() + "'失败，部门名称已存在");
        }
        // 如果父节点不为正常状态,则不允许新增子节点
        SysDept parent = sysDeptDao.getById(param.getParentId());
        if (ObjectUtil.notEqual(parent.getStatus(), Const.StatusNormal)) {
            throw new ServiceException("部门停用,不允许新增子部门");
        }

        SysDept entity = MapstructUtil.convert(param, SysDept.class);
        Assert.notNull(entity, "添加对象不能为空");
        entity.setAncestors(parent.getAncestors() + StringConst.SEPARATOR + entity.getParentId());
        return sysDeptDao.save(entity);
    }

    @Transactional
    public boolean update(SysDeptParam param) {

        Long deptId = param.getDeptId();
        dataScopeService.checkDeptDataScope(deptId);

        if (sysDeptDao.checkExistDeptName(param)) {
            throw new ServiceException("修改部门'" + param.getDeptName() + "'失败，部门名称已存在");
        }
        if (param.getParentId().equals(deptId)) {
            throw new ServiceException("修改部门'" + param.getDeptName() + "'失败，上级部门不能为自身");
        }
        // 禁用状态
        if (StrUtil.equals(param.getStatus(), Const.StatusDisable)) {
            if (sysDeptDao.hasNormalChildByDeptId(deptId)) {
                throw new ServiceException("该部门包含未停用的子部门！");
            }
            if (sysDeptDao.checkDeptHasUserByDeptId(deptId)) {
                throw new ServiceException("该部门包含用户,不允许禁用");
            }
        }
        SysDept entity = MapstructUtil.convert(param, SysDept.class);
        Assert.notNull(entity, "修改对象不能为空");

        SysDept oldEntity = sysDeptDao.getById(param.getDeptId());
        if (ObjectUtil.notEqual(oldEntity.getParentId(), param.getParentId())) {
            // 如果是新父部门 则校验是否具有新父部门权限 避免越权
            SysDept newParent = sysDeptDao.getById(param.getParentId());
            if (ObjectUtil.isNotNull(newParent) && ObjectUtil.isNotNull(oldEntity)) {
                String newAncestors = newParent.getAncestors() + StringConst.SEPARATOR + newParent.getDeptId();
                String oldAncestors = oldEntity.getAncestors();
                entity.setAncestors(newAncestors);
                sysDeptDao.updateDeptChildren(param.getDeptId(), newAncestors, oldAncestors);
            }
        }
//            // 如果该部门是启用状态，则启用该部门的所有上级部门
//            updateParentDeptStatusNormal(dept);
        return sysDeptDao.updateById(entity);
    }

    public boolean removeById(Long deptId) {
        if (sysDeptDao.hasChildByDeptId(deptId)) {
            throw new ServiceException("存在下级部门,不允许删除");
        }
        if (sysDeptDao.checkDeptHasUserByDeptId(deptId)) {
            throw new ServiceException("部门存在用户,不允许删除");
        }
        dataScopeService.checkDeptDataScope(deptId);
        return sysDeptDao.removeById(deptId);
    }


    /**
     * 获取未被禁用的部门树列表
     */
    public List<Tree<Long>> tree(SysDeptParam param) {
        // 只查询未禁用部门
        param.setStatus(Const.StatusNormal);

        List<SysDeptVo> deptList = this.list(param);
        if (CollUtil.isEmpty(deptList)) {
            return CollUtil.newArrayList();
        }
        return TreeBuildUtil.build(deptList, (dept, tree) ->
                tree.setId(dept.getDeptId())
                        .setParentId(dept.getParentId())
                        .setName(dept.getDeptName())
                        .setWeight(dept.getSortNum()));
    }

    /**
     * 根据角色ID查询部门树信息(已分配)
     *
     * @param roleId 角色ID
     * @return 选中部门列表
     */
    public List<Long> listAllocatedDeptIdByRoleId(Long roleId) {
        return sysRoleDeptDao.listAllocatedDeptIdByRoleId(roleId);
    }
}
